import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import {
  Between,
  In,
  Like,
  Not,
  Repository,
  // Brackets,
  // getRepository
} from 'typeorm';
import ProductionOrder from '@main/entities/service/admin/production/production-order.entity';
import { UtilService } from '@main/shared/services/util.service';
import SysDictionary from '@main/entities/service/admin/sys/sys-dictionary.entity';
import WipOrderReport from '@main/entities/service/admin/wip/wip-order-report.entity';
import { WipOrderReportService } from '@main/service/modules/admin/wip/orderReport/orderReport.service';
import WipShutdownList from '@main/entities/service/admin/wip/wip-shutdown-list.entity';
import BaseMachine from '@main/entities/service/admin/base/base-machine.entity';
import { ApiException } from '@main/common/exceptions/api.exception';
import { generateExcelFn } from '@main/excel';
import { SysOperationLogService } from '../../system/operationLog/operationLog.service';
import { format } from 'date-fns';
import ReportFormPeriodStatusMonitoring from '@main/entities/service/admin/reportForm/report-form-period-status-monitoring.entity';
import WipMachineMaintain from '@main/entities/service/admin/wip/wip-machine-maintain.entity';

function getCurrentTimeRangeTimestamps(data) {
  // 获取当前时间
  let currentDate = new Date();
  let currentHours = currentDate.getHours();
  let currentMinutes = currentDate.getMinutes();
  let currentTotalMinutes = currentHours * 60 + currentMinutes;

  // 遍历数据中的时间段
  for (let i = 0; i < data.length; i++) {
    let extend1 = parseTime(data[i].extend1);
    let extend2 = parseTime(data[i].extend2);

    let extend1TotalMinutes = extend1.hours * 60 + extend1.minutes;
    let extend2TotalMinutes = extend2.hours * 60 + extend2.minutes;

    // 检查时间段是否跨越午夜
    if (extend1TotalMinutes <= extend2TotalMinutes) {
      // 时间段未跨越午夜的情况
      if (currentTotalMinutes >= extend1TotalMinutes && currentTotalMinutes < extend2TotalMinutes) {
        return {
          timestamp1: setTimeOnDate(currentDate, extend1.hours, extend1.minutes),
          timestamp2: setTimeOnDate(currentDate, extend2.hours, extend2.minutes),
        };
      }
    } else {
      // 时间段跨越午夜的情况
      if (
        currentTotalMinutes >= extend1TotalMinutes ||
        currentTotalMinutes < extend2TotalMinutes + (24 * 60 - extend1TotalMinutes)
      ) {
        let timestamp1, timestamp2;
        if (currentTotalMinutes < extend2TotalMinutes + (24 * 60 - extend1TotalMinutes)) {
          // 当前时间在第二天的时间段内
          timestamp1 = setTimeOnDate(currentDate, extend2.hours, extend2.minutes);
          // 将日期向后推一天
          let previousDate = new Date(currentDate);
          previousDate.setDate(previousDate.getDate() + 1);
          timestamp2 = setTimeOnDate(previousDate, extend1.hours, extend1.minutes);
        } else {
          // 当前时间在第一天的时间段内
          timestamp1 = setTimeOnDate(currentDate, extend1.hours, extend1.minutes);
          timestamp2 = setTimeOnDate(currentDate, extend2.hours, extend2.minutes);
        }
        return { timestamp1, timestamp2 };
      }
    }
  }

  return null; // 如果当前时间不在任何时间段内
}

// 设置指定小时和分钟的时间
function setTimeOnDate(date, hours, minutes) {
  let newDate = new Date(date);
  newDate.setHours(hours, minutes, 0, 0);
  return newDate;
}

// 解析时间字符串，返回小时和分钟
function parseTime(timeStr) {
  let parts = timeStr.split(':');
  return {
    hours: parseInt(parts[0], 10),
    minutes: parseInt(parts[1], 10),
  };
}

@Injectable()
export class ProductionOrderService {
  constructor(
    @InjectRepository(ProductionOrder)
    private orderRepository: Repository<ProductionOrder>,
    @InjectRepository(WipOrderReport)
    private wipOrderReport: Repository<WipOrderReport>,
    @InjectRepository(SysDictionary)
    private dictionaryRepository: Repository<SysDictionary>,
    private util: UtilService,
    private orderReport: WipOrderReportService,
    @InjectRepository(WipShutdownList)
    private shutdownListRepository: Repository<WipShutdownList>,
    private operationLogService: SysOperationLogService,
    @InjectRepository(BaseMachine)
    private machineRepository: Repository<BaseMachine>,
    @InjectRepository(ReportFormPeriodStatusMonitoring)
    private reportFormPeriodStatusMonitoringRepository: Repository<ReportFormPeriodStatusMonitoring>,
    @InjectRepository(WipMachineMaintain)
    private machineMaintainRepository: Repository<WipMachineMaintain>
  ) {}

  async list(data) {
    const where = {};

    if (data) {
      const { orderStatusCodeList } = data;

      if (orderStatusCodeList && orderStatusCodeList.length) {
        where['orderStatusCode'] = In(orderStatusCodeList);
      }
    }

    return await this.orderRepository.find({ where });
  }

  async getOrderByMachineCode(data) {
    const { proSearch, machineCode } = data;

    const where: any = [
      {
        machineCode,
        orderStatusCode: Not('40'),
      },
    ];

    if (proSearch) {
      where.push(
        {
          orderCode: Like(`%${proSearch}%`),
        },
        {
          materialCode: Like(`%${proSearch}%`),
        }
      );
    }
    return await this.orderRepository.find({
      where,
      order: {
        proOrder: 'ASC',
      },
    });
  }

  /**
   * 罗列所有配置
   */
  async page(data) {
    const { pageSize, pageNum, entity = {} } = data;

    const {
      fastSearch,
      orderStatusCode,
      customerNo,
      customerOrderNo,
      machineCode,
      scheduledStartTime,
      scheduledEndTime,
      ids = [],
    } = entity;

    const obj = {};

    if (orderStatusCode) {
      obj['orderStatusCode'] = Like(`%${orderStatusCode}%`);
    }

    if (customerNo) {
      obj['customerNo'] = Like(`%${customerNo}%`);
    }

    if (customerOrderNo) {
      obj['customerOrderNo'] = Like(`%${customerOrderNo}%`);
    }

    if (machineCode) {
      obj['machineCode'] = Like(`%${machineCode}%`);
    }

    if (scheduledStartTime && scheduledStartTime.length)
      obj['scheduledStartTime'] = Between(scheduledStartTime[0], scheduledStartTime[1]);

    if (scheduledEndTime && scheduledEndTime.length)
      obj['scheduledEndTime'] = Between(scheduledEndTime[0], scheduledEndTime[1]);

    const where: any = [obj];

    if (fastSearch) {
      where.push(
        {
          materialName: Like(`%${fastSearch}%`),
        },
        {
          materialCode: Like(`%${fastSearch}%`),
        },
        {
          orderCode: Like(`%${fastSearch}%`),
        },
        {
          customName: Like(`%${fastSearch}%`),
        },
        {
          customShort: Like(`%${fastSearch}%`),
        },
        {
          customCode: Like(`%${fastSearch}%`),
        }
      );

      // console.log(where);
      // where['$or'] = [
      //   { materialName: Like(`%${fastSearch}%`) },
      //   { orderCode: Like(`%${fastSearch}%`) },
      //   { customerName: Like(`%${fastSearch}%`) },
      //   { customerShort: Like(`%${fastSearch}%`) },
      // ];

      // where['$or'] = new Brackets((qb) => {
      //   qb.where('materialName LIKE :search', { search: `%${fastSearch}%` })
      //     .orWhere('orderCode LIKE :search', { search: `%${fastSearch}%` })
      //     .orWhere('customName LIKE :search', { search: `%${fastSearch}%` })
      //     .orWhere('customShort LIKE :search', { search: `%${fastSearch}%` });
      // });
    }

    // console.log(where)

    if (ids && ids.length) {
      for (const item of where) {
        item['id'] = In(ids);
      }
    }

    const [list, total] = await this.orderRepository.findAndCount({
      where,
      order: {
        updateTime: 'DESC',
      },
      take: pageSize,
      skip: (pageNum - 1) * pageSize,
    });

    // machineCode   scheduledStartTime  scheduledEndTime customerDeliveryDate
    const newList = await Promise.all(
      list?.map(async (item) => {
        const { machineCode, scheduledStartTime, scheduledEndTime, customerDeliveryDate } = item;
        if (scheduledStartTime) {
          item.scheduledStartTime = format(
            new Date(scheduledStartTime),
            'yyyy-MM-dd HH:mm:ss'
          ) as any;
        }
        if (scheduledEndTime) {
          item.scheduledEndTime = format(new Date(scheduledEndTime), 'yyyy-MM-dd HH:mm:ss') as any;
        }
        if (customerDeliveryDate) {
          item.customerDeliveryDate = format(
            new Date(customerDeliveryDate),
            'yyyy-MM-dd HH:mm:ss'
          ) as any;
        }
        const obj = await this.machineRepository.findOne({ where: { machineCode } });
        return {
          ...(obj || {}),
          ...item,
        };
      })
    );

    return [newList, total];
  }

  async export(dto, lang) {
    const [list] = await this.page(dto);

    if (!list || !(list as any).length) {
      throw new ApiException(10052);
    }

    const dataList = list;

    return await generateExcelFn(
      {
        sheetName: 'productionOrder',
        mainHeaderList: [
          {
            label: 'machineName',
          },
          {
            label: 'materialName',
          },
          {
            label: 'version',
          },
          {
            label: 'orderCode',
          },
          {
            label: 'orderNum',
          },
          {
            label: 'paperboardNum',
          },
          {
            label: 'orderStatusName',
          },
          {
            label: 'proOrder',
          },
          {
            label: 'scheduledStartTime',
          },
          {
            label: 'scheduledEndTime',
          },
          {
            label: 'customName',
          },
          {
            label: 'customerNo',
          },
          {
            label: 'customerOrderNo',
          },
          {
            label: 'customerDeliveryDate',
          },
          {
            label: 'erpNo',
          },
          {
            label: 'remark',
          },
        ],
        dataList,
      },
      lang
    );
  }

  /**
   * 新增
   */
  async add(data, languageType, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];
    const orderCode = `MO${this.util.nowDateValue()}${this.util.generateRandomNumberValue(4)}`;

    const result = await this.orderRepository.find({ where: { orderCode } });

    if (result && result.length) {
      this.add(data, languageType, user, mac, ip, syncHostSqlite);

      return;
    }

    const orderStatusName = await this.getOrderStatusName('20', languageType);

    const order = await this.orderRepository.insert({
      ...data,
      orderCode,
      orderStatusCode: '20',
      orderStatusName,
      createName: user.nickName,
      createUserName: user.userName,
      updateName: user.nickName,
      updateUserName: user.userName,
    });
    databaseOperationLogList.push({
      type: 'add',
      dataType: 'obj',
      database: 'ProductionOrder',
      checkOnlyKeyList: [],
      data: order,
      whereObj: null,
      remark: `ProductionOrder表新增数据`,
    });

    await this.operationLogService.add(
      {
        type: 'add',
        msg: `工单列表管理模块新增工单信息`,
        databaseOperationLogList,
        remark: `新增工单${data.orderCode}`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
  }

  async getOrderStatusName(orderStatusCode, languageType) {
    const list = await this.dictionaryRepository.find({
      where: { dictionaryTypeCode: 'order_status', languageType },
    });

    const obj = list.find((item) => item.dictionaryCode === orderStatusCode);

    if (obj) return obj.dictionaryName;

    return null;
  }

  async update(data, languageType, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];

    const { id, orderStatusCode, reportNum } = data;

    const orderStatusName = await this.getOrderStatusName(orderStatusCode, languageType);

    const obj = await this.orderRepository.findOne({ where: { id } });

    const producedNum = (obj.producedNum || 0) + (reportNum || 0);

    await this.orderRepository.update(
      { id },
      {
        orderStatusCode,
        orderStatusName,
        producedNum,
        actualCompleteDate: (orderStatusCode === '40' ? new Date().getTime() : null) as any,
        updateName: user.nickName,
        updateUserName: user.userName,
      }
    );
    databaseOperationLogList.push({
      type: 'update',
      dataType: 'obj',
      database: 'ProductionOrder',
      checkOnlyKeyList: [],
      data: {
        orderStatusCode,
        orderStatusName,
        producedNum,
        actualCompleteDate: orderStatusCode === '40' ? new Date().getTime() : null,
        updateName: user.nickName,
        updateUserName: user.userName,
      },
      whereObj: { id },
      remark: `ProductionOrder表更新工单信息`,
    });
    await this.operationLogService.add(
      {
        type: 'update',
        msg: `工单列表管理模块更新工单信息`,
        databaseOperationLogList,
        remark: `更新工单${data.orderCode}`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );

    await this.orderReport.add({ ...obj, ...data }, user, mac, ip, syncHostSqlite);
  }

  async updateAdjuest(data, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];
    const { id, adjuestNum, orderCode } = data;

    const nowTime = new Date().getTime();

    const obj = await this.wipOrderReport.findOne({
      where: { orderCode, reportFinishStatus: 0 },
      order: {
        createTime: 'DESC',
      },
    });

    let adjuestDuration = 0;

    if (obj) {
      const { createTime } = obj;

      adjuestDuration = Number(((nowTime - new Date(createTime).getTime()) / 1000 / 60).toFixed(2));
    }

    await this.wipOrderReport.update(
      { id: obj.id },
      {
        adjuestNum,
        adjuestSuccessTime: nowTime,
        adjuestDuration,
        updateName: user.nickName,
        updateUserName: user.userName,
      }
    );

    await this.orderRepository.update(
      { id },
      {
        adjuestNum,
        adjuestSuccessTime: nowTime,
        adjuestDuration,
        updateName: user.nickName,
        updateUserName: user.userName,
      }
    );

    databaseOperationLogList.push(
      {
        type: 'update',
        dataType: 'obj',
        database: 'ProductionOrder',
        checkOnlyKeyList: [],
        data: {
          adjuestNum,
          adjuestSuccessTime: nowTime,
          updateName: user.nickName,
          updateUserName: user.userName,
        },
        whereObj: { id },
        remark: `ProductionOrder表更新工单信息`,
      },
      {
        type: 'update',
        dataType: 'obj',
        database: 'WipOrderReport',
        checkOnlyKeyList: [],
        data: {
          adjuestNum,
          adjuestSuccessTime: nowTime,
          adjuestDuration,
          updateName: user.nickName,
          updateUserName: user.userName,
        },
        whereObj: { id: obj.id },
        remark: `WipOrderReport表更新工单信息`,
      }
    );

    await this.operationLogService.add(
      {
        type: 'update',
        msg: `工单列表管理模块更新工单信息`,
        databaseOperationLogList,
        remark: `更新工单${data.orderCode}`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
  }

  async updateMachine(data, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];
    const { id, machineCode } = data;
    await this.orderRepository.update(
      { id },
      { machineCode, updateName: user.nickName, updateUserName: user.userName }
    );

    databaseOperationLogList.push({
      type: 'update',
      dataType: 'obj',
      database: 'ProductionOrder',
      checkOnlyKeyList: [],
      data: { machineCode, updateName: user.nickName, updateUserName: user.userName },
      whereObj: { id },
      remark: `ProductionOrder表更新工单信息`,
    });

    await this.operationLogService.add(
      {
        type: 'update',
        msg: `工单列表管理模块更新工单信息`,
        databaseOperationLogList,
        remark: `更新工单${data.orderCode}`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
  }

  async updatePro(list, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];
    for (let i = 0; i < list.length; i++) {
      const { id, proOrder } = list[i];

      await this.orderRepository.update(
        { id },
        { proOrder, updateName: user.nickName, updateUserName: user.userName }
      );

      databaseOperationLogList.push({
        type: 'update',
        dataType: 'obj',
        database: 'ProductionOrder',
        checkOnlyKeyList: [],
        data: { proOrder, updateName: user.nickName, updateUserName: user.userName },
        whereObj: { id },
        remark: `ProductionOrder表更新工单信息`,
      });

      await this.operationLogService.add(
        {
          type: 'update',
          msg: `工单列表管理模块更新工单信息`,
          databaseOperationLogList,
          remark: `更新工单`,
          mac,
          ip,
          syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
        },
        user
      );
    }
  }

  /**
   * 删除
   */
  async delete(idList, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];

    await this.orderRepository.delete(idList);

    databaseOperationLogList.push({
      type: 'delete',
      dataType: 'array',
      database: 'ProductionOrder',
      checkOnlyKeyList: [],
      data: null,
      whereObj: idList,
      remark: `ProductionOrder表删除工单信息`,
    });

    await this.operationLogService.add(
      {
        type: 'delete',
        msg: `工单列表管理模块删除工单信息`,
        databaseOperationLogList,
        remark: `删除工单`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
  }

  /**
   * 删除arr
   */
  async deleteRecords(ids: string[]) {
    const result = await this.orderRepository
      .createQueryBuilder()
      .delete()
      .from(ProductionOrder)
      .where('id IN (:...ids)', { ids })
      .execute();
    // await this.orderRepository.delete()
    // .where("id IN (:...ids)", { ids })
    // .execute();
    return result;
  }

  /**
   * 调整生产工单顺序
   */
  async adjustOrder(erpNo, newData: Partial<ProductionOrder>) {
    const result = await this.orderRepository
      .createQueryBuilder()
      .update(ProductionOrder)
      .set(newData)
      .where('erpNo = :erpNo', { erpNo })
      .execute();
    return result;
  }

  // async isExistKey(data) {
  //   const {materialCode,version} = data;

  //   const result = await this.orderRepository.findOne({ where: { materialCode,version } });

  //   return result;
  // }

  async getColumnsList() {
    const entityMetadata = this.orderRepository.metadata;

    const list = entityMetadata.columns.map((column) => {
      return {
        key: column.propertyName,
        comment: column.comment,
      };
    });

    return list;
  }

  async statisticsByShiftTime(data) {
    const { machineCode, startTime, endTime } = data;

    let orderNum = 0;

    let goodProductsNum = 0;

    let badNum = 0;

    let badRate = 0;

    let toBeProducedNum = 0;

    let adjuestNum = 0;

    let productionTime = 0;

    let shutdownTime = 0;

    let shutdownNum = 0;

    let allProducedNum = 0;

    const list = await this.orderRepository.find({
      where: [
        {
          machineCode,
          scheduledStartTime: Between(startTime, endTime),
        },
        {
          machineCode,
          orderStatusCode: '30',
        },
      ],
    });

    // console.log(list);

    await Promise.all(
      list.map(async (item) => {
        const {
          orderNum: iOrderNum,
          producedNum: iProducedNum,
          adjuestNum: iAdjuestNum,
          orderStatusCode,
        } = item;

        const reportList = await this.wipOrderReport.find({
          where: {
            orderCode: item.orderCode,
            machineCode,
          },
        });

        if (reportList && reportList.length) {
          let addProducedNum = 0;

          await Promise.all(
            reportList.map(async (rItem) => {
              const {
                reportNum,
                reportConfirmNum,
                goodNum,
                badNum: iBadNum,
                reportTime,
                createTime,
                reportStatus,
                reportCode,
                reportFinishStatus,
              } = rItem;

              goodProductsNum += goodNum;

              badNum += iBadNum;

              addProducedNum += reportStatus === 1 ? reportConfirmNum : reportNum;

              if (reportFinishStatus === 0) {
                // console.log(new Date(createTime).getTime());
                productionTime += new Date().getTime() - new Date(createTime).getTime();
              } else {
                productionTime +=
                  ((reportTime as any) || new Date().getTime()) - new Date(createTime).getTime();
              }

              const shutdownList = await this.shutdownListRepository.find({
                where: {
                  reportCode,
                },
              });

              if (shutdownList && shutdownList.length) {
                for (const sItem of shutdownList) {
                  const { shutdownStartTime, shutdownEndTime } = sItem;
                  shutdownTime +=
                    ((shutdownEndTime as any) || new Date().getTime()) - (shutdownStartTime as any);
                }

                shutdownNum += shutdownList.length;
              }
            })
          );

          if (orderStatusCode !== '40') {
            if (addProducedNum < iOrderNum) {
              toBeProducedNum += iOrderNum - addProducedNum;
            }
          }
        }

        allProducedNum += iProducedNum;

        orderNum += iOrderNum;

        adjuestNum += iAdjuestNum;
      })
    );

    return [
      {
        orderNum,
        goodProductsNum,
        badNum,
        badRate,
        toBeProducedNum,
        adjuestNum,
        productionTime,
        shutdownTime,
        shutdownNum,
      },
    ];
  }

  async onDutyProductionProgress(languageType) {
    const shiftTimeTypeList = await this.dictionaryRepository.find({
      where: { dictionaryTypeCode: 'shift_time_type', languageType },
    });

    const timestamps = getCurrentTimeRangeTimestamps(shiftTimeTypeList);

    let nowTime = new Date().getTime();

    let startTime: any = nowTime;

    let endTime: any = nowTime;

    if (timestamps) {
      startTime = new Date(timestamps.timestamp1).getTime();

      endTime = new Date(timestamps.timestamp2).getTime();
    }

    const list = await this.orderRepository.find({
      where: {
        scheduledStartTime: Between(startTime, endTime),
      },
    });

    const machineList = await this.machineRepository.find();

    let planTheSingular = list.length;

    let completionSingular = 0;

    let planProduction = 0; // 计划产量

    let actualProduction = 0; // 实际产量

    let machineData = {};

    if (list.length) {
      await Promise.all(
        list.map(async (item) => {
          const { orderStatusCode, orderNum, orderCode, machineCode } = item;

          if (orderStatusCode === '40') {
            completionSingular += 1;

            const list2 = await this.wipOrderReport.find({
              where: {
                orderCode,
              },
            });

            if (list2 && list2.length) {
              if (!machineData[machineCode]) {
                machineData[machineCode] = {
                  actualOutput: 0,
                  electricityConsumption: 0,
                  waterConsumption: 0,
                  useTime: 0,
                };
              }

              for (const lItem of list2) {
                const {
                  reportFinishStatus,
                  reportNum,
                  reportConfirmNum,
                  reportStatus,
                  waterConsumption = 0,
                  electricityConsumption = 0,
                  createTime,
                  reportTime,
                } = lItem;

                if (reportFinishStatus === 1) {
                  if (reportStatus === 1) {
                    actualProduction += reportConfirmNum;

                    machineData[machineCode].actualOutput += reportConfirmNum;
                  } else {
                    actualProduction += reportNum;

                    machineData[machineCode].actualOutput += reportNum;
                  }

                  machineData[machineCode].electricityConsumption += electricityConsumption;

                  machineData[machineCode].waterConsumption += waterConsumption;

                  machineData[machineCode].useTime +=
                    new Date(reportTime).getTime() - new Date(createTime).getTime();
                }
              }
            }
          }

          planProduction += orderNum;
        })
      );
    }

    const remainingSingular = planTheSingular - completionSingular;

    const remainingProduction = planProduction - actualProduction; // 剩余产量

    await Promise.all(
      machineList.map(async (item) => {
        const { machineCode } = item;

        const machineStatusObj = await this.reportFormPeriodStatusMonitoringRepository.findOne({
          where: {
            machineCode,
          },
          order: {
            createTime: 'DESC',
          },
        });

        if (machineStatusObj) {
          item['machineStatus'] = Number(machineStatusObj.machineStatus);
        } else {
          item['machineStatus'] = 0;
        }

        let numMaintenance = 0;

        const machineMaintainList = await this.machineMaintainRepository.find({
          where: {
            machineCode,
            maintenanceStatus: '0',
            planMaintenanceDate: Between(startTime, endTime),
          },
        });

        if (machineMaintainList && machineMaintainList.length) {
          numMaintenance = machineMaintainList.length;
        }

        item['numMaintenance'] = numMaintenance;

        if (machineData[machineCode]) {
          const { actualOutput, useTime, electricityConsumption, waterConsumption } =
            machineData[machineCode];

          item['avgSpeed'] = Math.ceil(actualOutput / (useTime / 1000 / 60));

          item['actualOutput'] = actualOutput;

          item['electricityConsumption'] = electricityConsumption;

          item['waterConsumption'] = waterConsumption;
        } else {
          item['avgSpeed'] = 0;

          item['actualOutput'] = 0;

          item['electricityConsumption'] = 0;

          item['waterConsumption'] = 0;
        }
      })
    );

    return {
      planTheSingular,
      completionSingular,
      remainingSingular,
      planProduction,
      actualProduction,
      remainingProduction,
      machineStateVoList: machineList,
    };
  }
}
